SSH Key Authentication
It has become increasingly widely known that SSH authentication can be passwordless or semi-passwordless using a cryptographic strategy known as PKI or Public Key Infrastructure. Unfortunately, far too many people, professionals and amateurs alike, fail to understand the factors which determine how secure a Public Key Infrastructure is, and implement this in a manner which reduces security. Passphraseless Keys The biggest mistake people make is to generate a private key which is not protected by a passphrase. The motivation for this is clear as without a full understanding of the functionality available from SSH Keys, users don't want to type their password when logging into a large number of systems. Private Keys stored on servers An unfortunate common practice in large infrastructures is for users to keep a private key, usually with no passphrase, on a server which they use as a gateway to access other servers. This is always a bad idea, but is especially bad when private keys exist on a bastion host, providing full passwordless access to some or all critical infrastructure. Personal Keys with access to root accounts Another unfortunate common practice is to use the same key pair for access to individual accounts as well as to root accounts. It can be necessary or very useful to have direct key-based access to a root account, and if you are going to connect as root or another system user, it's safer to use a key than a password. For a number of reasons that largely have to do with people not being as responsible as they intend to be, I recommend to generate a separate keypair for access other than to individual / personal accounts. Generating a keypair These instructions will guide you to create a 2048-bit or longer RSA key. On UNIX/Linux (including Mac OS X) At the terminal, run: ssh-keygen -t rsa -b 2048 Typically you'll want to accept the default location for your key, and the output / interaction will look something like this: jryan@bacon:~$ ssh-keygen -t rsa -b 2048 Generating public/private rsa key pair. Enter file in which to save the key (/home/jryan/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/jryan/.ssh/id_rsa. Your public key has been saved in /home/jryan/.ssh/id_rsa.pub. The key fingerprint is: b9:22:52:b0:ba:94:4d:b7:8b:2e:ba:0a:f5:4e:d1:be jryan@bacon The key's randomart image is: +--[ RSA 2048]----+ | | | | | . | | o . . | | o.o.. S | | o+o.o. . | |oo..+.o . | |oo +...o | |B.oo..E | +-----------------+ Don't forget to use a good passphrase. Recently the trend toward complex to remember passwords has taken a turn toward passphrases with multiple short words which are easier to remember and nearly impossible to attack with brute force. On Windows The most common SSH client used on Windows is called PuTTY and includes a tool call PuTTYgen to generate SSH Keys. Allowing access to a UNIX account Now that you have a public / private key pair, you'll want to deposit the public key, and only the public key, on servers you are trying to access. For my account 'justizin' on 'meteor.bitmonk.net', I can allow access based on my newly generated keypair by doing something along these lines: UNIX users scp ~/.ssh/id_rsa.pub justizin@meteor.bitmonk.net: This would place my new id_rsa.pub file at /home/justizin on the host meteor.bitmonk.net. Next, I connect with my password to the host: $ ssh justizin@meteor.bitmonk.net The authenticity of host 'meteor.bitmonk.net (173.230.155.166)' can't be established. RSA key fingerprint is ad:e1:ae:e0:d5:f2:a1:e5:43:8e:71:42:e1:55:0f:98. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'meteor.bitmonk.net,173.230.155.166' (RSA) to the list of known hosts. justizin@meteor.bitmonk.net's password: Linux meteor 2.6.39.1-linode34 #1 SMP Tue Jun 21 10:29:24 EDT 2011 i686 GNU/Linux Ubuntu 10.04.2 LTS Welcome to Ubuntu! * Documentation: https://help.ubuntu.com/ Last login: Thu Sep 8 11:35:51 2011 from 38.127.199.123 justizin@meteor:~$ cat id_rsa.pub >> .ssh/authorized_keys Windows users Windows users will need to use PSCP or another file transfer method to transfer their key. Cut and paste into a text editor is an option. Additionally, most Windows key generation tools I've used create a key of the format: ---- BEGIN SSH2 PUBLIC KEY Comment: "rsa, Justin Ryan@SomeStupid-PC, Thu Sep 08 2011 \ 00:44:18" AAAAB3NzaC1kc3MAAAEBALOFOeFEb1Z9UbU3rUcZD5JdhT5r6x8Sdl04MsJIoeKeWN3rgS Bi8h2uvwJ4xTBH5l8YwnXp0/MaIvOImk+44TVU3Pj9rF5YTyRzOnRuQZjl+iUBflMmGvg3 XLSalWRc+4oR4vDGSdjrpDFwxAOD00wrDy5tofGm5Ky69dNj/7hF3BdBf3TBVst5GilV6A grTKHExbpAWfvBUcr2MOXMXo7X4Ah/Q+uGhm2drvHTHCy+QVx4evD7d8wRBBHSnI3awnI4 yuoRTr4XguHWMR3MKvP7QvIInH6ALHelnI+fPGLvtMJEGHHPk+Env7jMuZwPBnpdAB6mfl bk2KCeMp9/nvEAAAAVAKT5eTTxBgXjvMMkPLhBd80P7q2/AAABAQCqI4mu9gyCTMOxKYKO BKqV7z7susxzGbH+sVV1i9C2gYJq+NCThlSpbTEFYjQrLmaRl3AKr15FY4L+3kEtlYvrrI 5W2sE3RtHVxT4AjPngRwP2whPLcEmurv8Bk5YIiLdMncwG/XN6nRn2AKHrhHdCNnGVfRQW SqnCeFkz1PKarPjY3Mn5ekF/NoAIMT5C/eHaM8gzzYqbLBje+6TRBpTqIsqXJUJCVnWo5x rO+vlPVEE0kGJo7DYqFQVAIYJESttQHNzjJSjLRdXPGUy0zxpyZL8G4Tji6qd5VnBrKrON 7kBDKj5mrIZlDisxRH7EA2F+THXga+mvFJdXboOzL0veAAABAQCKemRDcvuKKu7KICyPuj nsQY3MLWp79zmeH62tAz4pxcguJs3vaFMlVzElGb4s0qghQ3zxOgnYqwwAPAsRWIB9bSMA rEb8SdrKCtPaumy9frp8t9ITLqunsw+L+zUZhr36x/A1oXcyWFcHvouvsrJVa2ZOYZIl0b xbuboiEW3BaiKNYJZWz3qguwiHB5gBHlxChAloqi07N5owhWzmQKEIM0EUuTfYEmb00v75 d94qzLzbmol0thTj4Y519PIxhTChLd+Lz5gv+Ozmouy1K0Qu2TOIsq8XxpjqhYf0ZJ0Nwo dE5+1d/FqdUc1kc14B3/3sAjR7SS0cVo7rbERTksvs END SSH2 PUBLIC KEY This format is not suitable for placement in authorized_keys, and may be converted with: ssh-keygen -i -f id_rsa.pub >> .ssh/authorized_keys In both cases above, if the authorized_keys file exists, my new key will only be appended. The Authentication Agent The basic configuration of SSH private / public key is great for one person on one workstation or laptop connecting to a handful of servers, always directly from the laptop. As one works to manage and/or work within a larger infrastructure, it is often necessary to connect between servers directly using key authentication. The SSH protocol is designed to facilitate this using an authentication agent. The SSH Agent allows you to authenticate with your key many times without retyping your passphrase, but can also be forwarded through multiple hosts. Consider the following situation, at work, I have full access to machines in the 10.0.0.0/8 private space allocated by RFC 1918. At home, by definition, I have no access to these machines, but I have access to one machine which is available on the public Internet, as well as our private network. I want to connect to a machine 'dev-ops' which lives in RFC 1918 space from home, without using a VPN. If I connect to the bastion host with agent forwarding enabled, I can use the private key on my laptop to connect to a machine within our RFC 1918 space, the most direct way is by passing the -A commandline option. Simplified output of such a session from my mac is below: bash-3.2$ ssh -A bastion.bitmonk.net Linux bastion-s1 2.6.32-28-server #55-Ubuntu SMP Mon Jan 10 23:57:16 UTC 2011 x86_64 GNU/Linux Ubuntu 10.04.2 LTS Welcome to the Ubuntu Server! * Documentation: http://www.ubuntu.com/server/doc Last login: Fri Oct 28 18:49:42 2011 from 10.4.1.111 justin@bastion-s1:~$ ssh some-internal-host Linux some-internal-host 2.6.32-31-server #61-Ubuntu SMP Fri Apr 8 19:44:42 UTC 2011 x86_64 GNU/Linux Ubuntu 10.04.2 LTS Welcome to the Ubuntu Server! * Documentation: http://www.ubuntu.com/server/doc Last login: Sat Oct 22 02:04:21 2011 from 10.4.1.111 justin@some-internal-host:~$ As you can see, I was not prompted for a password to connect to the internal host. It is not always recommend, but often practical, to forward the auth agent for many or all of your connections, which you can do by setting something like the following in your ~/.ssh/config file: Host * ForwardAgent yes If you connect via SSH to some hosts whose administrators you don't trust, you may want to be more specific, such as: Host *.bitmonk.net ForwardAgent yes This will only forward your authentication agent when a hostname, as specified on the command line, matches the pattern "*.bitmonk.net". Category:Security